package com.luo.storage.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.luo.common.exception.BadRequestException;
import com.luo.common.exception.ForbiddenException;
import com.luo.storage.config.JwtProperties;
import com.luo.storage.enums.UserStatus;
import com.luo.storage.mapper.UserRoleMapper;
import com.luo.storage.model.domain.PageQueryParams;
import com.luo.storage.model.domain.Role;
import com.luo.storage.model.domain.User;
import com.luo.storage.model.domain.UserRole;
import com.luo.storage.model.dto.UserLoginDto;
import com.luo.storage.mapper.UserMapper;
import com.luo.storage.service.RoleService;
import com.luo.storage.service.UserRoleService;
import com.luo.storage.service.UserService;
import com.luo.storage.model.vo.UserLoginVo;
import com.luo.storage.utils.JwtTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private JwtTool jwtTool;
    @Autowired
    private JwtProperties jwtProperties;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private RoleService roleService;

    /**
     * 用户条件分页查询
     * @param pageQueryParams
     * @return
     */
    @Override
    public IPage<User> userPage(PageQueryParams pageQueryParams) {
        Integer pageNum = pageQueryParams.getPageNum();
        Integer pageSize = pageQueryParams.getPageSize();
        IPage<User> page = new Page<>(pageNum,pageSize);
        IPage<User> userIPage = userMapper.userPage(page, pageQueryParams);

        List<User> users = userIPage.getRecords();
        for(User user : users){
            List<Role> roles = getUserRoles(user.getId());
            user.setRole(roles);
        }
        return userIPage;
    }

    /**
     * 获取用户角色列表
     * @param userId
     * @return
     */
    private List<Role> getUserRoles(Long userId){
        //根据userId查询中间表的对象集合
        List<UserRole> userRoles = userRoleService.list(Wrappers.<UserRole>lambdaQuery()
                .eq(UserRole::getUserId, userId));
        if (userRoles.isEmpty()){
            return Collections.emptyList();
        }
        //将对象转换成roleId的集合
        List<Long> roleIds = userRoles.stream()
                .map(UserRole::getRoleId)
                .collect(Collectors.toList());

        //上面的集合ids当作查找条件
        return roleService.list(Wrappers.<Role>lambdaQuery()
                .in(Role::getId,roleIds));
    }

    /**
     * 用户登录
     * @param userLoginDto
     * @return
     */
    @Override
    public UserLoginVo login(UserLoginDto userLoginDto) {
        //1) 获取对应用户
        String username = userLoginDto.getUsername();
        String password = userLoginDto.getPassword();
        User user = userMapper.selectOne(Wrappers.<User>lambdaQuery()
                .eq(User::getUsername, username)
                .eq(User::getPassword, password));

        //2) 检查状态
//        Assert.isNull(user,"用户不存在");
        if (Objects.isNull(user)){
            throw new BadRequestException("用户不存在");
        }
        if(user.getStatus()== UserStatus.FORZEN){
            throw new ForbiddenException("用户已被冻结");
        }

        //3) token
        String token = jwtTool.createToken(user.getId(), jwtProperties.getTokenTTL());

        //4) UserLoginVo
        UserLoginVo userLoginVo = new UserLoginVo();
        userLoginVo.setUserId(user.getId());
        userLoginVo.setToken(token);
        userLoginVo.setUsername(username);
        userLoginVo.setNickname(user.getName());

        return userLoginVo;
    }
}
